/*
 * Time.h
 *
 *	Author: stravant
 *	Description:
 *		
 */

#ifndef TIME_H_
#define TIME_H_

#include "Include.h"

#if defined(OS_WIN)
#include <windows.h>
#endif

#if defined(OS_POSIX)
#include <sys/time.h>
#endif

class Time;

class TimeDelta {
public:
	TimeDelta(): mDelta(0) {}

	static TimeDelta FromDays(int64 days);
	static TimeDelta FromHours(int64 hours);
	static TimeDelta FromMinutes(int64 mins);
	static TimeDelta FromSeconds(int64 s);
	static TimeDelta FromMilliseconds(int64 ms);
	static TimeDelta FromMicroseconds(int64 us);

	int inDays() const;
	int inHours() const;
	int inMinutes() const;
	int64 inSeconds() const;
	int64 inMilliseconds() const;
	int64 inMicroseconds() const;
	double inSecondsF() const;


	TimeDelta& operator=(TimeDelta other) {
		mDelta = other.mDelta;
		return *this;
	}

	//additive
	TimeDelta operator+(TimeDelta other) const {
		return TimeDelta(mDelta + other.mDelta);
	}
	TimeDelta operator-(TimeDelta other) const {
		return TimeDelta(mDelta - other.mDelta);
	}

	TimeDelta& operator+=(TimeDelta other) {
		mDelta += other.mDelta;
		return *this;
	}
	TimeDelta& operator-=(TimeDelta other) {
		mDelta -= other.mDelta;
		return *this;
	}
	TimeDelta operator-() const {
		return TimeDelta(-mDelta);
	}

	//multiplicative too on deltas
	TimeDelta operator*(int64 a) const {
		return TimeDelta(mDelta * a);
	}
	TimeDelta operator/(int64 a) const {
		return TimeDelta(mDelta / a);
	}
	TimeDelta& operator*=(int64 a) {
		mDelta *= a;
		return *this;
	}
	TimeDelta& operator/=(int64 a) {
		mDelta /= a;
		return *this;
	}
	int64 operator/(TimeDelta a) const {
		return mDelta / a.mDelta;
	}

	//comparisons
	bool operator==(TimeDelta other) const {
		return mDelta == other.mDelta;
	}
	bool operator!=(TimeDelta other) const {
		return mDelta != other.mDelta;
	}
	bool operator<(TimeDelta other) const {
		return mDelta < other.mDelta;
	}
	bool operator<=(TimeDelta other) const {
		return mDelta <= other.mDelta;
	}
	bool operator>(TimeDelta other) const {
		return mDelta > other.mDelta;
	}
	bool operator>=(TimeDelta other) const {
		return mDelta >= other.mDelta;
	}

	~TimeDelta() {}
private:
	friend class Time;
	TimeDelta(int64 delta): mDelta(delta) {}
	int64 mDelta;
};

class Time {
public:
	//conversion factors
	static const int64 kMillisecondsPerSecond = 1000;
	static const int64 kMicrosecondsPerMillisecond = 1000;
	static const int64 kMicrosecondsPerSecond = kMicrosecondsPerMillisecond *
												kMillisecondsPerSecond;
	static const int64 kMicrosecondsPerMinute = kMicrosecondsPerSecond * 60;
	static const int64 kMicrosecondsPerHour = kMicrosecondsPerMinute * 60;
	static const int64 kMicrosecondsPerDay = kMicrosecondsPerHour * 24;
	static const int64 kMicrosecondsPerWeek = kMicrosecondsPerDay * 7;
	static const int64 kNanosecondsPerMicrosecond = 1000;
	static const int64 kNanosecondsPerSecond = 	kNanosecondsPerMicrosecond *
												kMicrosecondsPerSecond;

	static Time UnixEpoch();
	static Time Now();

	//copy ctor
	Time(const Time& other): mUs(other.mUs) {}
	~Time() {}

	//mutators
	Time& operator=(const Time& other) {
		mUs = other.mUs;
		return *this;
	}
	TimeDelta operator-(const Time& other) const {
		return TimeDelta(mUs - other.mUs);
	}
	Time operator+(const TimeDelta& other) const {
		return Time(mUs + other.mDelta);
	}
	Time& operator+=(const TimeDelta& other) {
		mUs += other.mDelta;
		return *this;
	}
	Time& operator-=(const TimeDelta& other) {
		mUs -= other.mDelta;
		return *this;
	}

	//comparisons
	bool operator==(const Time& other) {
		return mUs == other.mUs;
	}
	bool operator!=(const Time& other) {
		return mUs != other.mUs;
	}
	bool operator<(const Time& other) {
		return mUs < other.mUs;
	}
	bool operator>(const Time& other) {
		return mUs > other.mUs;
	}
	bool operator<=(const Time& other) {
		return mUs <= other.mUs;
	}
	bool operator>=(const Time& other) {
		return mUs >= other.mUs;
	}

	bool isNull() {
		return mUs == 0;
	}
private:
	static const int64 kMicrosecondOffset;

	Time(): mUs(0) {}
	Time(int64 us): mUs(us) {}
	friend class TimeDelta;
	int64 mUs;
};

#endif /* TIME_H_ */
























